<?php
/**
 * 
 * app 疯狂工厂
 * @author will
 *
 */
class App_factory {
	static private $time_now = 0;
	
	/**
	 * 获取可偷列表
	 * @param <int> $uin
	 * @param <int> $refresh_type 是否刷新cache (0 => 不刷新，缓存过期则刷新   1 => 不刷新，缓存过期也不刷新    2 => 强制刷新)
	 */
	static public function getFriendsList($uin , $refresh_type = 0) {
		$list = array();
		$time_now = time();
		
		$Db = loadDB();
		
		$refresh = $refresh_type == 2 ? true : false;
		
		// 先查缓存
		if($refresh_type != 2) {
			$info = $Db->getOne("SELECT * FROM `app_factory_friends_cache` WHERE `uin` = {$uin}");
			if(!empty($info)) {
				// 判断缓存是否过期  (10分钟)
				if($refresh_type != 1 && $time_now > $info['time'] + 5) {
					$refresh = true;
				}
			} else {
				$refresh = true;
			}
		}
		
		if(!$refresh) {
			$list = explode("\n" , $info['list']);
			//echo 'no refresh';
		} else {
			// 得到好友列表，可偷钱，不足的用随机用户补足
			loadLib('Friend');
			$friends = Friend::get($uin);
			$opened_friends = array();
			
			// 判断这些人是否已经开通了游戏
			if(!empty($friends)) {
				$opened_result = $Db->getAll("SELECT `uin` FROM `app_factory_info` WHERE `uin` IN (" . implode(',' , $friends) . ")");
				if(!empty($opened_result)) {
					foreach($opened_result as $row) {
						$opened_friends[$row['uin']] = $row['uin'];
					}
				}
			}
			
			// 不足，随机补齐
			$min = 20;
			$opened_friends_count = count($opened_friends);
			if($opened_friends_count < $min) {
				$limit = $min - $opened_friends_count;
				$opened_result = $Db->getAll("SELECT `uin` FROM `app_factory_info` ORDER BY RAND() LIMIT {$limit}");
				if(!empty($opened_result)) {
					foreach($opened_result as $row) {
						if($row['uin'] == $uin) continue;
						$opened_friends[$row['uin']] = $row['uin'];
					}
				}
			}
			
			// 为了方便，再查一次。以后改成set memcache
			$update_array = array(
				'list' => implode("\n" , $opened_friends),
				'time' => $time_now,
			);
			$info = $Db->getOne("SELECT * FROM `app_factory_friends_cache` WHERE `uin` = {$uin}");
			if(empty($info)) {
				$update_array['uin'] = $uin;
				$Db->doInsert('app_factory_friends_cache' , $update_array);
			} else {
				$Db->doUpdate('app_factory_friends_cache' , $update_array , '`uin` = ' . $uin);
			}
			
			//echo 'refresh';
			$list = array_values( $opened_friends );
		}
		
		
		return $list;
	}
	
	/**
	 * 获取工厂主人信息
	 * @param <int> $uin
	 */
	static public function getInfo($uin) {
		$Db = loadDB();
		$info = $Db->getOne("SELECT * FROM `app_factory_info` WHERE `uin` = {$uin}");
		
		if(empty($info)) {
			return $info;
		}
		
		// unserialize
		$info['lines_info'] = empty($info['lines_info']) ? array() : unserialize($info['lines_info']);
		$info['lines_info'] = self::_FormatLinesInfo($info['lines_info']);
		
		$info['secretary'] = $info['secretary'] === '' ? array() : explode("\n" , $info['secretary']);
		$info['police'] = $info['police'] === '' ? array() : explode("\n" , $info['police']);
		
		return empty($info) ? array() : $info;
	}
	
	/**
	 * 刷新 timer 表
	 * @param <int> $uin
	 * @param <array> $old_info
	 * @param <boolean> $update_owner 是否更新主人的值
	 */
	static public function updateState($uin , $old_info = array() , $update_owner = false) {
		$Db = loadDB();
		
		$info = empty($old_info) ? self::getInfo($uin) : $old_info;
		
		self::$time_now = isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time();
		
		$update_array = array();
		
		// 更新生产线
		self::_updateLinesState($info, $update_array , $update_owner);
		
		// 更新体力
		self::_updateHPState($info, $update_array , $update_owner);
		
		// 更新秘书
		self::_updateSecretaryState($info, $update_array , $update_owner);
		
		// 更新保安
		self::_updatePoliceState($info, $update_array , $update_owner);
		
		// 更新数据库
		if(!empty($update_array)) {
			$Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $uin);
		}

		return $info;
	}
	
	/**
	 * 更新生产线
	 */
	static private function _updateLinesState(&$info , &$update_array , $update_owner) {
		// 判断是否需要更新，只更新正在生产中的状态
		if($info['lines_info']['state'] != 1) return;
		
		// 判断是否到收钱时间了
		if(self::$time_now < $info['lines_timer']) return;
		
		// 改变 lines_state 状态
		$info['lines_info']['state'] = 2;
		$info['lines_info']['earned'] = $info['lines_info']['earn'];
		
		$update_array['lines_info'] = serialize( self::_FormatLinesInfo($info['lines_info']) );
	}

	
	/**
	 * 更新体力
	 */
	static private function _updateHPState(&$info , &$update_array , $update_owner) {
		// 判断是否需要更新
		if($info['hp'] >= 100) return;
		
		// 判断可以恢复几点体力
		$restore_timer = 300;	// 15分钟恢复1点体力
		$diff = self::$time_now - $info['hp_timer'];
		$restore_hp = floor( $diff / $restore_timer );

		if($restore_hp <= 0) return;
		
		// 修改数值
		$info['hp'] = min(100 , $info['hp'] + $restore_hp);
		$info['hp_timer'] = $info['hp_timer'] + ( $restore_timer * $restore_hp );
		
		// 判断是否要更新数据库
		if($update_owner) {
			$update_array['hp'] = $info['hp'];
			$update_array['hp_timer'] = $info['hp_timer'];
		}
	}
	
	/**
	 * 更新秘书
	 */
	static private function _updateSecretaryState(&$info , &$update_array , $update_owner) {
		// 判断是否需要更新
		if(self::$time_now < $info['secretary_timer']) return;
		
		// 修改数值
		$info['secretary'] = array();
		$update_array['secretary'] = '';
	}
	
	/**
	 * 更新保安
	 */
	static private function _updatePoliceState(&$info , &$update_array , $update_owner) {
		// 判断是否需要更新
		if(self::$time_now < $info['police_timer']) return;
		
		// 修改数值
		$info['police'] = array();
		$update_array['police'] = '';
	}
	
	/**
	 * 初始化 timer 表
	 * @param <int> $uin
	 */
	static public function initInfo($uin) {
		$time_now = time();
		
		$info_insert_array = array(
			'uin' => $uin,
			'ability' => 0,
			'hp' => 100,
			'hp_timer' => $time_now,
			'level' => 1,
			'lines' => 1,
			'lines_timer' => 0,
			'lines_info' => '',
			'lines_add_timer' => 0,
			'secretary' => '',
			'secretary_timer' => 0,
			'police' => '',
			'police_timer' => 0,
		);
		
		$Db = loadDB();
		$success = $Db->doInsert('app_factory_info' , $info_insert_array);
		
		
		return $success ? 0 : 1200;
	}
	
	
	/**
	 * 开始生产线
	 * @param <int> $uin
	 * @param <array> $info
	 */
	static public function startLines($uin , $info = array()) {
		if(empty($info)) {
			$info = self::getInfo($uin);
		}
		
		$dairy_earn = self::getLevelInfo($info['lines'] , 'daily_earn');
		
		// 把 line_state 置 1
		$lines_info_array = array(
			'earn' => $dairy_earn,
			'earned' => 0,
			'state' => 1,
			'thief' => array(),
		);
		$update_array = array(
			'lines_timer' => time() + 900,
			'lines_info' => serialize( self::_FormatLinesInfo($lines_info_array) ),
		);
		
		$Db = loadDB();
		$success = $Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $uin);

		return $success ? 0 : 1201;
	}
	
	/**
	 * 结束生产线
	 * @param <int> $uin
	 */
	static public function endLines($uin) {
		// 把 line_state 置 0
		$lines_info_array = array(
			'earn' => 0,
			'earned' => 0,
			'state' => 0,
			'thief' => array(),
		);
		$update_array = array(
			'lines_timer' => time() + 70,
			'lines_info' => serialize( self::_FormatLinesInfo($lines_info_array) ),
		);
		
		$Db = loadDB();
		$success = $Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $uin);
		
		return $success ? 0 : 1202;
	}
	
	/**
	 * 增加一条生产线
	 * @param <int> $uin
	 * @param <int> $old_lines
	 */
	static public function addLines($uin , $old_lines = false) {
		if($old_lines === false) {
			$info = self::getInfo($uin);
			$lines = $info['lines'];
		} else {
			$lines = $old_lines;
		}
		
		$update_array = array(
			'lines' => $lines + 1,
			'lines_add_timer' => time(),
		);
		
		$Db = loadDB();
		$success = $Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $uin);
		
		return $success ? 0 : 1204;
	}
	
	/**
	 * 招秘书
	 * @param <int> $uin
	 * @param <int> $to_uin 被招者的uin，如果是电脑，则是0
	 * @param <array> $old_secretary
	 */
	static public function hireSecretary($uin , $to_uin , $old_secretary = false) {
		if($old_secretary === false) {
			$info = self::updateState($uin , null , true);	// 需要获取更新后的数据
			$secretary = $info['secretary'];
		} else {
			$secretary = $old_secretary;
		}
		
		if($to_uin == 0) {
			// 雇佣的是电脑
			$secretary[] = $to_uin;
		} else {
			// 判断该用户是否已被雇佣过了，要去重
			if(!in_array($to_uin , $secretary)) {
				$secretary[] = $to_uin;
			}
		}
		
		$update_array = array(
			'secretary' => implode("\n" , $secretary),
			'secretary_timer' => time() + (86400 * 7),	// 有效期一星期
		);
		
		$Db = loadDB();
		$success = $Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $uin);
		
		return $success ? 0 : 1205;
	}
	
	/**
	 * 招保安
	 * @param <int> $uin
	 * @param <int> $to_uin 被招者的uin，如果是电脑，则是0
	 * @param <array> $old_police
	 */
	static public function hirePolice($uin , $to_uin , $old_police = false) {
		if($old_police === false) {
			$info = self::updateState($uin , null , true);	// 需要获取更新后的数据
			$police = $info['police'];
		} else {
			$police = $old_police;
		}
		
		if($to_uin == 0) {
			// 雇佣的是电脑
			$police[] = $to_uin;
		} else {
			// 判断该用户是否已被雇佣过了，要去重
			if(!in_array($to_uin , $police)) {
				$police[] = $to_uin;
			}
		}
		
		$update_array = array(
			'police' => implode("\n" , $police),
			'police_timer' => time() + (86400 * 7),	// 有效期一星期
		);
		
		$Db = loadDB();
		$success = $Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $uin);
		
		return $success ? 0 : 1205;
	}
	
	/**
	 * 偷钱
	 * @param <int> $uin 偷钱的人
	 * @param <int> $steal_uin 被偷的人
	 * @param <int> $money
	 * @param <array> $info
	 */
	static public function steal($uin , $steal_uin , $money , $info = false) {
		loadLib('Currency');
		$code = Currency::update('app_factory' , $uin , $money);
		if($code !== 0) {
			return $code;
		}
		
		if(empty($info)) {
			$info = self::getInfo($uin);
		}
		
		$lines_info_array = $info['lines_info'];
		
		// 把 line_state 置 1
		$lines_info_array['earned'] = $lines_info_array['earned'] - $money;
		$lines_info_array['thief'][] = $uin;
		
		$update_array = array(
			'lines_info' => serialize( self::_FormatLinesInfo($lines_info_array) ),
		);
		
		$Db = loadDB();
		$success = $Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $steal_uin);

		return $success ? 0 : 1209;
	}
	
	
	/**
	 * 获取偷窃时间、次数表
	 * @param <int> $uin
	 */
	static public function getStealTimes($uin) {
		$Db = loadDB();
		
		self::$time_now = isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time();
		
		$info = $Db->getOne("SELECT * FROM `app_factory_steal_times` WHERE `uin` = {$uin}");
		if(empty($info)) {
			$insert_array = array(
				'uin' => $uin,
				'secretary_times' => 0,
				'secretary_time' => 0,
				'police_times' => 0,
				'police_time' => 0,
			);
			$Db->doInsert('app_factory_steal_times' , $insert_array);
			
			$info = $insert_array;
		}
		
		// 判断最后一次偷的时间
		$today_ts = strtotime( date('Y-m-d' , self::$time_now) );
		if($info['secretary_time'] < $today_ts) $info['secretary_times'] = 0;
		if($info['police_time'] < $today_ts) $info['police_times'] = 0;

		return $info;
	}
	
	static public function updateStealTimes($uin , $type , $info = false) {
		if(empty($info)) {
			$info = self::getStealTimes($uin);
		}
		
		self::$time_now = isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time();
		
		$update_array = array();
		
		if($type == 'secretary') {
			$update_array['secretary_times'] = $info['secretary_times'] + 1;
			$update_array['secretary_time'] = self::$time_now;
		} else if($type == 'police') {
			$update_array['police_times'] = $info['police_times'] + 1;
			$update_array['police_time'] = self::$time_now;
		}
		
		$Db = loadDB();
		$success = $Db->doUpdate('app_factory_steal_times' , $update_array , '`uin` = ' . $uin);

		return $success ? 0 : 1209;
	}


	/**
	 * 更新体力
	 */
	static private function updateHP($uin , $num , $info = false) {
		if(empty($info)) {
			$info = self::updateState($uin , null , true);
		}

		$new_hp = $info['hp'] + $num;
		if($new_hp > 100) $new_hp = 100;
		else if($new_hp < 0) $new_hp = 0;

		if($new_hp == $info['hp']) return 0;
		
		// 判断是否要更新数据库
		if($update_owner) {
			$update_array['hp'] = $new_hp;
			$update_array['hp_timer'] = time();
		}

		$success = $Db->doUpdate('app_factory_info' , $update_array , '`uin` = ' . $uin);

		return $success ? 0 : 1213;
	}
	
	
	/**
	 * encode 信息
	 * @param <array> $data
	 */
	static private function _FormatLinesInfo($data) {
		if(!isset($data['earn'])) $data['earn'] = 0;
		if(!isset($data['earned'])) $data['earned'] = 0;
		if(!isset($data['state'])) $data['state'] = 0;
		if(!isset($data['thief'])) $data['thief'] = array();
		
		return $data;
	}

	/**
	 * 获取用户的PK台信息
	 * @param <int> $uin
	 */
	static public function getPkInfo($uin) {
		$Db = loadDB();

		$info = $Db->getOne("SELECT * FROM `app_factory_pk` WHERE `uin` = {$uin}");
		if(empty($info)) {
			$insert_array = array(
				'uin' => $uin,
				'level' => 1,
				'timer' => 0,
			);
			$Db->doInsert('app_factory_pk' , $insert_array);
			return $insert_array;
		}

		return $info;
	}

	/**
	 * 获取PK奖励信息
	 * @param <int> $level
	 */
	static public function getPkAwards($level) {
		if($level <= 1 || $level > 100) return false;

		$currency = 400 + (( $level - 1 ) * 150);

		return array('currency' => $currency);
	}

	/**
	 * 获取PK每个级别的最多人数
	 * @param <int> $level
	 */
	static public function getPKMaxUin($level) {
		if($level >= 2 && $level <= 10) return 200;
		if($level >= 11 && $level <= 15) return 100;
		if($level >= 16 && $level <= 20) return 50;
		if($level >= 21 && $level <= 30) return 10;
		if($level >= 31 && $level <= 50) return 5;
		if($level >= 51 && $level <= 99) return 3;
		if($level >= 100) return 1;
	}


	/**
	 * PK!!!
	 * @param <int> $uin
	 * @param <int> $to_uin
	 * @param <boolean> @win 引用传参 true 代表 $uin 赢了，false 代表 $uin 输了
	 */
	static public function PK($uin , $to_uin , &$win) {
		$rand = rand(1 , 100);
		if($rand <= 50) {
			$win = true;
			return 0;
		} else {
			$win = false;
			return 0;
		}
	}

	/**
	 * 更新用户level
	 * @param <int> $uin
	 * @param <int> $level
	 */
	static public function pk_toLevel($uin , $level) {
		$Db = loadDB();

		$success = $Db->query("UPDATE `app_factory_pk` SET `level` = {$level} WHERE `uin` = {$uin}");

		return $success ? 0 : 1216;
	}
	

	
	
	
	
	// ----------------------------- 配置 -----------------------------
	/**
	 * 获取每个等级的信息
	 * @param <int> @level
	 * @param <string> @type
	 */
	static public function getLevelInfo($level , $type = false) {
		$arr = array('daily_earn' => 0);
		switch($level) {
			case 1  : $arr = array('daily_earn' => 1000 , 'addlines_fee' => 1133); break;
			case 2  : $arr = array('daily_earn' => 1100 , 'addlines_fee' => 1133); break;
			case 3  : $arr = array('daily_earn' => 1300 , 'addlines_fee' => 1133); break;
			case 4  : $arr = array('daily_earn' => 1600 , 'addlines_fee' => 1133 , 'upgrade_fee' => 3900); break;
			case 5  : $arr = array('daily_earn' => 2000 , 'addlines_fee' => 2300); break;
			case 6  : $arr = array('daily_earn' => 2500 , 'addlines_fee' => 2300); break;
			case 7  : $arr = array('daily_earn' => 3100 , 'addlines_fee' => 2300); break;
			case 8  : $arr = array('daily_earn' => 3800 , 'addlines_fee' => 2300 , 'upgrade_fee' => 21700); break;
			case 9  : $arr = array('daily_earn' => 4600 , 'addlines_fee' => 6700); break;
			case 10 : $arr = array('daily_earn' => 5500 , 'addlines_fee' => 6700); break;
			case 11 : $arr = array('daily_earn' => 6500 , 'addlines_fee' => 6700); break;
			case 12 : $arr = array('daily_earn' => 7600 , 'addlines_fee' => 6700); break;
			case 13 : $arr = array('daily_earn' => 8800 , 'addlines_fee' => 6700); break;
			case 14 : $arr = array('daily_earn' => 10100 , 'addlines_fee' => 6700); break;
			case 15 : $arr = array('daily_earn' => 11500 , 'addlines_fee' => 6700); break;
			case 16 : $arr = array('daily_earn' => 13000 , 'addlines_fee' => 6700 , 'upgrade_fee' => 172500); break;
			case 17 : $arr = array('daily_earn' => 14600 , 'addlines_fee' => 27233); break;
			case 18 : $arr = array('daily_earn' => 16300 , 'addlines_fee' => 27233); break;
			case 19 : $arr = array('daily_earn' => 18100 , 'addlines_fee' => 27233); break;
			case 20 : $arr = array('daily_earn' => 20000 , 'addlines_fee' => 27233); break;
			case 21 : $arr = array('daily_earn' => 22000 , 'addlines_fee' => 27233); break;
			case 22 : $arr = array('daily_earn' => 24100 , 'addlines_fee' => 27233); break;
			case 23 : $arr = array('daily_earn' => 26300 , 'addlines_fee' => 27233); break;
			case 24 : $arr = array('daily_earn' => 28600 , 'addlines_fee' => 27233); break;
			case 25 : $arr = array('daily_earn' => 31000 , 'addlines_fee' => 27233); break;
			case 26 : $arr = array('daily_earn' => 33500 , 'addlines_fee' => 27233); break;
			case 27 : $arr = array('daily_earn' => 36100 , 'addlines_fee' => 27233); break;
			case 28 : $arr = array('daily_earn' => 38800 , 'addlines_fee' => 27233); break;
			case 29 : $arr = array('daily_earn' => 41600 , 'addlines_fee' => 27233); break;
			case 30 : $arr = array('daily_earn' => 44500 , 'addlines_fee' => 27233); break;
			case 31 : $arr = array('daily_earn' => 47500 , 'addlines_fee' => 27233); break;
			case 32 : $arr = array('daily_earn' => 50600 , 'addlines_fee' => 27233 , 'upgrade_fee' => 1472500); break;
			case 33 : $arr = array('daily_earn' => 53800 , 'addlines_fee' => 113100); break;
			case 34 : $arr = array('daily_earn' => 57100 , 'addlines_fee' => 113100); break;
			case 35 : $arr = array('daily_earn' => 60500 , 'addlines_fee' => 113100); break;
			case 36 : $arr = array('daily_earn' => 64000 , 'addlines_fee' => 113100); break;
			case 37 : $arr = array('daily_earn' => 67600 , 'addlines_fee' => 113100); break;
			case 38 : $arr = array('daily_earn' => 71300 , 'addlines_fee' => 113100); break;
			case 39 : $arr = array('daily_earn' => 75100 , 'addlines_fee' => 113100); break;
			case 40 : $arr = array('daily_earn' => 79000 , 'addlines_fee' => 113100 , 'upgrade_fee' => 1472500); break;
			case 41 : $arr = array('daily_earn' => 83000 , 'addlines_fee' => 113100); break;
			case 42 : $arr = array('daily_earn' => 87100 , 'addlines_fee' => 113100); break;
			case 43 : $arr = array('daily_earn' => 91300 , 'addlines_fee' => 113100); break;
			case 44 : $arr = array('daily_earn' => 95600 , 'addlines_fee' => 113100); break;
			case 45 : $arr = array('daily_earn' => 100000 , 'addlines_fee' => 113100); break;
			case 46 : $arr = array('daily_earn' => 104500 , 'addlines_fee' => 113100); break;
			case 47 : $arr = array('daily_earn' => 109100 , 'addlines_fee' => 113100); break;
			case 48 : $arr = array('daily_earn' => 113800 , 'addlines_fee' => 113100 , 'upgrade_fee' => 1472500); break;
			case 49 : $arr = array('daily_earn' => 118600 , 'addlines_fee' => 113100); break;
			case 50 : $arr = array('daily_earn' => 123500 , 'addlines_fee' => 113100); break;
			case 51 : $arr = array('daily_earn' => 128500 , 'addlines_fee' => 113100); break;
			case 52 : $arr = array('daily_earn' => 133600 , 'addlines_fee' => 113100); break;
			case 53 : $arr = array('daily_earn' => 138800 , 'addlines_fee' => 113100); break;
			case 54 : $arr = array('daily_earn' => 144100 , 'addlines_fee' => 113100); break;
			case 55 : $arr = array('daily_earn' => 149500 , 'addlines_fee' => 113100); break;
			case 56 : $arr = array('daily_earn' => 155000 , 'addlines_fee' => 113100 , 'upgrade_fee' => 1472500); break;
			case 57 : $arr = array('daily_earn' => 160600 , 'addlines_fee' => 113100); break;
			case 58 : $arr = array('daily_earn' => 166300 , 'addlines_fee' => 113100); break;
			case 59 : $arr = array('daily_earn' => 172100 , 'addlines_fee' => 113100); break;
			case 60 : $arr = array('daily_earn' => 178000 , 'addlines_fee' => 113100); break;
			case 61 : $arr = array('daily_earn' => 184000 , 'addlines_fee' => 113100); break;
			case 62 : $arr = array('daily_earn' => 190100 , 'addlines_fee' => 113100); break;
			case 63 : $arr = array('daily_earn' => 196300 , 'addlines_fee' => 113100); break;
		}
		
		return empty($type) ? $arr : $arr[$type];
	}
}


# end of script

